// 
// Copyright 2010 Classpath Pty Ltd <opensource@classpath.com.au>
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 

**
** The `Router` class is responsible for calculating the steps to get from one version of the database to another.
**
internal class Router {

    **
    ** Storage for the list of [Migrations]`Migration` that this `Router` knows how to route between.
    **
    Migration[] migrations

    **
    ** Creates a new `Router` storing the supplied [Migrations]`Migration` for routing between.
    **
    internal new make(Migration[] migrations) {
        Pod.of(this).log.debug("${typeof}.make(${migrations}) - start")
        this.migrations = migrations
        Pod.of(this).log.debug("${typeof}.make(${migrations}) - end")
    }

    **
    ** Attempts to calculate a route from the specified `sys::Version` to the specified `sys::Version`.
    ** The route calculation doesn't do any back tracing, or branch analysis, so don't ask too much of it.
    **
    Migration[] route(Version from, Version to) {
        Pod.of(this).log.debug("${typeof}.route(${from}, ${to}) - start")
        route := [,]
        if (from != to) {
            up := from < to
            start := up ? from : to
            end := up ? to : from
            Migration? last
            while (last == null || last.to < end) {
                if (last == null) {
                    next := migrations.find { it.from == start }
                    if (next == null) {
                        Pod.of(this).log.err("Cannot find a route from ${start}")
                        throw Err("Cannot find a route from ${start}")
                    }
                    route.add(next)
                    last = next
                }
                else {
                    next := migrations.find { it.from == last.to }
                    if (next == null) {
                        Pod.of(this).log.err("Cannot find a route from ${last.to}")
                        throw Err("Cannot find a route from ${last.to}")
                    }
                    route.add(next)
                    last = next
                }
            }
            if (!up) {
                route = route.reverse
            }
        }
        Pod.of(this).log.debug("${typeof}.route(${from}, ${to}) - end - returning ${route}")
        return route
    }

}
